#ifndef __I_EVENT_PROCESSOR_H__
#define __I_EVENT_PROCESSOR_H__

#include "I_Thread.h"
#include "I_Event.h"
#include "I_Action.h"

#define  DEFAULT_STACK_SIZE 0
#define  DEFAULT_THREAD_DETACHED 0

#define  MAX_THREAD_NAME_LEN 16
#define  MAX_THREAD_GROUP 16
#define  MAX_TYPE_THREADS 128
#define  MAX_DETACHED_THREADS 20

typedef int EventType;

extern const int ET_CALL;

class Processor
{
public:
	virtual ~Processor() {}
	virtual bool start(int number_of_threads, int detached = DEFAULT_THREAD_DETACHED, size_t stacksize = DEFAULT_STACK_SIZE) = 0;
	virtual void shutdown() = 0;

protected:
	Processor() {}

private:
	Processor(const Processor &);
	Processor &operator=(const Processor &);
};



class EventProcessor : public Processor
{
public:
	EventProcessor();
	~EventProcessor();


	bool start(int number_of_threads, int detached = DEFAULT_THREAD_DETACHED, size_t stacksize = DEFAULT_STACK_SIZE);

	EventType spawn_event_threads(int n_threads, const char *et_name, int detached = DEFAULT_THREAD_DETACHED, size_t stacksize = DEFAULT_STACK_SIZE);

	Event *spawn_thread(Continuation *cont, const char *thr_name);

	void shutdown();


	EThread *assign_thread(EventType et);

	/******schedule******/
	Event *schedule_imm(Continuation *c, EventType et = ET_CALL, int callback_event = EVENT_IMMDIATE);
	Event *schedule_imm_signal(Continuation *c, EventType et = ET_CALL, int callback_event = EVENT_IMMDIATE);
	Event *schedule_at(Continuation *c, ink_hrtime timeout_at, EventType et = ET_CALL, int callback_event = EVENT_INTERVAL);
	Event *schedule_every(Continuation *c, ink_hrtime period, EventType et = ET_CALL, int callback_event = EVENT_INTERVAL);

	off_t allocate_thread_spec(int size, EventType etype);

	EThread *all_ethreads[MAX_THREAD_GROUP * MAX_TYPE_THREADS];
	EThread *event_threads[MAX_THREAD_GROUP][MAX_TYPE_THREADS];
	EThread *all_dthreads[MAX_DETACHED_THREADS];
	int next_thread_for_type[MAX_THREAD_GROUP];
	int n_threads_for_type[MAX_THREAD_GROUP];

	int n_thread_group;
	int n_ethreads;
	int n_dthreads;
private:
	EventProcessor(const EventProcessor &);
	EventProcessor &operator=(const EventProcessor &);

	Event *schedule(Event *e, EventType etype, bool fast_signal = false);

	ink_mutex d_spaw_thread_mutex;
};

extern EventProcessor eventProcessor;


#endif //__I_EVENT_PROCESSOR_H__
